﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Universe.WCF.Behaviors.Test
{
    using System.Diagnostics;
    using System.IO;
    using System.ServiceModel;
    using System.Threading;

    using NUnit.Framework;

    // Mono 2.11.4 doesnt support multithreaded proxy
    
    [TestFixture]
    public class PerfomanceTests : BaseTest
    {
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            CrossInfo.AttachUnitTrace("WCF Tests. Perfomance");
        }

        [SetUp]
        public void SetUp()
        {
            MyEnvionment.ResetTcpPort();
            CrossInfo.NextTest();
        }

        [Test]
        public void Test_1A_Stress_Pure_Connection()
        {
            int duration = 10000;
            var numThreads = new[] { 1, 2, 4, 8 };

            MyEnvionment.ResetTcpPort();
            ServiceHost host = MyEnvionment.CreateService<IService1<int>, Service1<int>>();
            host.Open();

            ChannelFactory<IService1<int>> channel = MyEnvionment.CreateProxy<IService1<int>>();
            var service1 = channel.CreateChannel(MyEnvionment.GetEndPointUri<IService1<int>>());

            Action iteration = () =>
            {
                service1.GetData(new CompositeType() { BoolValue = true, StringValue = "Hi" });
            };

            foreach (var num in numThreads)
            {
                UnitStress.Run(num, duration, iteration);
            }
        }

        [Test]
        public void Test_1B_Stress_Pure_Connection_Using_ThreadLocal_Channel()
        {
            int duration = 10000;
            var numThreads = new[] { 1, 2, 4, 8 };

            MyEnvionment.ResetTcpPort();
            ServiceHost host = MyEnvionment.CreateService<IService1<int>, Service1<int>>();
            host.Open();

            Lazy<IService1<int>> service1 = new Lazy<IService1<int>>(() =>
            {
                ChannelFactory<IService1<int>> channel = MyEnvionment.CreateProxy<IService1<int>>();
                return channel.CreateChannel(MyEnvionment.GetEndPointUri<IService1<int>>());
            });

            Action iteration = () =>
            {
                service1.Value.GetData(new CompositeType() { BoolValue = true, StringValue = "Hi" });
            };

            foreach (var num in numThreads)
            {
                UnitStress.Run(num, duration, iteration, threadInitializer: iteration);
            }
        }

        [Test]
        public void Test_2A_Stress_All()
        {
            int duration = 10000;
            var numThreads = new[] { 1, 2, 4, 8 };

            // CONFIGURE Server Traffic profiler
            TrafficStatistic serverTraffic = new TrafficStatistic();
            var serverConfiguration = new TrafficStatisticConfiguration(
                delegate { },
                serverTraffic.Merge);

            TrafficStatistic clientTraffic = new TrafficStatistic();
            var clientConfiguration = new TrafficStatisticConfiguration(
                clientTraffic.Merge,
                delegate { });

            int arrivedId = 0;
            string arrivedCulture = null;

            var tdc = new TransparentDeliveryConfiguration(
                delegate(string action, DeliveryDictionary data)
                {
                    data.Set<int>("ID", 321);
                    data.Set<string>("Culture", "en-US");
                },
                delegate(string action, DeliveryDictionary data)
                {
                    arrivedId = data.Get<int>("ID");
                    arrivedCulture = data.Get<string>("Culture");
                });




            MyEnvionment.ResetTcpPort();
            ServiceHost host = MyEnvionment.CreateService<IService1<int>, Service1<int>>();
            host.Description.Behaviors.Add(new TrafficBehavior(serverConfiguration));
            host.Description.Behaviors.Add(new TransparentDeliveryBehavior(tdc));
            host.Open();

            ChannelFactory<IService1<int>> channel = MyEnvionment.CreateProxy<IService1<int>>();
            channel.Endpoint.Behaviors.Add(new TrafficBehavior(clientConfiguration));
            channel.Endpoint.Behaviors.Add(new TransparentDeliveryBehavior(tdc));
            var service1 = channel.CreateChannel(MyEnvionment.GetEndPointUri<IService1<int>>());

            Action iteration = () =>
            {
                service1.GetData(new CompositeType() { BoolValue = true, StringValue = "Hi" });
            };

            foreach (var num in numThreads)
            {
                UnitStress.Run(num, duration, iteration);
            }
        }
        [Test]
        public void Test_2B_Stress_All_Using_ThreadLocal_Channel()
        {
            int duration = 10000;
            var numThreads = new[] { 1, 2, 4, 8 };

            // CONFIGURE Server Traffic profiler
            TrafficStatistic serverTraffic = new TrafficStatistic();
            var serverConfiguration = new TrafficStatisticConfiguration(
                delegate { },
                serverTraffic.Merge);

            TrafficStatistic clientTraffic = new TrafficStatistic();
            var clientConfiguration = new TrafficStatisticConfiguration(
                clientTraffic.Merge,
                delegate { });

            int arrivedId = 0;
            string arrivedCulture = null;

            var tdc = new TransparentDeliveryConfiguration(
                delegate(string action, DeliveryDictionary data)
                {
                    data.Set<int>("ID", 321);
                    data.Set<string>("Culture", "en-US");
                },
                delegate(string action, DeliveryDictionary data)
                {
                    arrivedId = data.Get<int>("ID");
                    arrivedCulture = data.Get<string>("Culture");
                });




            MyEnvionment.ResetTcpPort();
            ServiceHost host = MyEnvionment.CreateService<IService1<int>, Service1<int>>();
            host.Description.Behaviors.Add(new TrafficBehavior(serverConfiguration));
            host.Description.Behaviors.Add(new TransparentDeliveryBehavior(tdc));
            host.Open();

            
            Lazy<IService1<int>> service1 = new Lazy<IService1<int>>(() =>
            {
                ChannelFactory<IService1<int>> channel = MyEnvionment.CreateProxy<IService1<int>>();
                channel.Endpoint.Behaviors.Add(new TrafficBehavior(clientConfiguration));
                channel.Endpoint.Behaviors.Add(new TransparentDeliveryBehavior(tdc));
                return channel.CreateChannel(MyEnvionment.GetEndPointUri<IService1<int>>());
            });

            Action iteration = () =>
            {
                service1.Value.GetData(new CompositeType() { BoolValue = true, StringValue = "Hi" });
            };

            foreach (var num in numThreads)
            {
                UnitStress.Run(num, duration, iteration, threadInitializer: iteration);
            }
        }



    }
}
